package org.xxpay.pay.channel.abcpay;

import com.abc.pay.client.*;
import com.abc.pay.client.ebus.PaymentRequest;
import com.abc.pay.client.ebus.QueryOrderRequest;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.xxpay.core.common.constant.PayConstant;
import org.xxpay.core.common.domain.api.AbstractRes;
import org.xxpay.core.common.domain.api.ApiBuilder;
import org.xxpay.core.common.domain.api.PayRes;
import org.xxpay.core.common.domain.api.msg.QueryRetMsg;
import org.xxpay.core.common.util.AmountUtil;
import org.xxpay.core.common.util.JsonUtil;
import org.xxpay.core.common.util.MyBase64;
import org.xxpay.core.common.util.MyLog;
import org.xxpay.core.common.vo.DBApplicationConfig;
import org.xxpay.core.entity.PayOrder;
import org.xxpay.pay.channel.BasePayment;
import org.xxpay.pay.mq.BaseNotify4MchPay;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedHashMap;

/**
 * @author: pangxiaoyu
 * @date: 2019年12月24日10:15:53
 * @description: 农行支付接口
 */
@Service
public class AbcpayPaymentService extends BasePayment {

    @Autowired
    public BaseNotify4MchPay baseNotify4MchPay;

    private static final MyLog _log = MyLog.getLog(AbcpayPaymentService.class);

    @Override
    public String getChannelName() {
        return AbcpayConfig.CHANNEL_NAME;
    }

    /**
     * 支付
     * @param payOrder
     * @return
     */
    @Override
    public AbstractRes pay(PayOrder payOrder) {
        String channelId = payOrder.getChannelId();
        AbstractRes retObj;
        switch (channelId) {
            case AbcpayConfig.CHANNEL_NAME_QR :
                retObj = doPay(payOrder, AbcpayConfig.PAY_TYPE_QR);
                break;
            case AbcpayConfig.CHANNEL_NAME_ALIPAY_QR :
                retObj = doPay(payOrder, AbcpayConfig.PAY_TYPE_ALIPAY_WX);
                break;
            case AbcpayConfig.CHANNEL_NAME_WXPAY_QR :
                retObj = doPay(payOrder, AbcpayConfig.PAY_TYPE_ALIPAY_H5);
                break;
            case AbcpayConfig.CHANNEL_NAME_ALIPAY_H5 :
                retObj = doPay(payOrder, AbcpayConfig.PAY_TYPE_ALIPAY_H5);
                break;
            case AbcpayConfig.CHANNEL_NAME_WXPAY_H5 :
                retObj = doPay(payOrder, AbcpayConfig.PAY_TYPE_WX_H5);
                break;
            default:
                return ApiBuilder.bizError("不支持的渠道[channelId="+channelId+"]");
        }
        return retObj;
    }

    /**
     * 支付
     * @param payOrder
     * @return
     */
    public AbstractRes doPay(PayOrder payOrder, String type) {
        _log.info(payConfig.getCertRootPath());
        PayRes retObj = ApiBuilder.buildSuccess(PayRes.class);
        Date date = new Date();
        SimpleDateFormat df1 = new SimpleDateFormat("yyyy/MM/dd");
        SimpleDateFormat df2 = new SimpleDateFormat("HH:mm:ss");

        PaymentRequest tPaymentRequest = new PaymentRequest();
        AbcpayConfig abcpayConfig = new AbcpayConfig(getPayParam(payOrder));
        //初始化参数
        try{
            MerchantPara para = MerchantConfig.getUniqueInstance().getPara();
            //设置商户编号。如果是多商户则在iMerchantIDList放置多条记录
            ArrayList<String> iMerchantIDList = new ArrayList<String>();
            iMerchantIDList.add(abcpayConfig.getMerchantId());
            para.setMerchantIDList(iMerchantIDList);
            //设置商户证书。如果是多商户则在iMerchantCertNameList放置多条记录。注意：商户证书名称顺序要与商户编号顺序一致

            FileUtil util = new FileUtil();
            ArrayList<byte[]> iMerchantCertList = new ArrayList<byte[]>();
            iMerchantCertList.add(util.readFile(AbcpayConfig.getCertPath() + File.separator + getChannelName() + File.separator + abcpayConfig.getPfx()));
            para.setMerchantCertFileList(iMerchantCertList);

            //设置商户证书密码。如果是多商户则在iMerchantPasswordList放置多条记录。注意：密码顺序要与商户编号顺序一致
            ArrayList<String> iMerchantPasswordList = new ArrayList<String>();
            iMerchantPasswordList.add(abcpayConfig.getPassword());// 商户私钥密码
            para.setMerchantCertPasswordList(iMerchantPasswordList);
            //#交易日志文件存放目录
            para.setLogPath(AbcpayConfig.getLogPath());

        }catch (TrxException e){
            _log.error(e+"");
        }

        //1、生成订单对象
        tPaymentRequest.dicOrder.put("PayTypeID", AbcpayConfig.PAY_TYPE_ID);           //设定交易类型
        tPaymentRequest.dicOrder.put("OrderDate", df1.format(date) );                  //设定订单日期 （必要信息 - YYYY/MM/DD）
        tPaymentRequest.dicOrder.put("OrderTime", df2.format(date));                   //设定订单时间 （必要信息 - HH:MM:SS）
        tPaymentRequest.dicOrder.put("orderTimeoutDate", "");                          //设定订单有效期
        tPaymentRequest.dicOrder.put("OrderNo", payOrder.getPayOrderId());             //设定订单编号 （必要信息）
        tPaymentRequest.dicOrder.put("CurrencyCode", AbcpayConfig.CURRENCY_CODE);      //设定交易币种 （156人民币）
        tPaymentRequest.dicOrder.put("OrderAmount", AmountUtil.convertCent2Dollar(payOrder.getAmount()+""));      //设定交易金额（元）
        tPaymentRequest.dicOrder.put("Fee", "");                                       //设定手续费金额
        tPaymentRequest.dicOrder.put("AccountNo", "");                                 //设定支付账户
        tPaymentRequest.dicOrder.put("OrderDesc", StringUtils.isBlank(payOrder.getBody()) ? "购物消费" : payOrder.getBody());                                 //设定订单说明
        tPaymentRequest.dicOrder.put("OrderURL", "");                                  //设定订单地址
        tPaymentRequest.dicOrder.put("ReceiverAddress", "");                           //收货地址
        tPaymentRequest.dicOrder.put("InstallmentMark", AbcpayConfig.INSTALLMENT_MARK);//分期标识
        tPaymentRequest.dicOrder.put("CommodityType", AbcpayConfig.COMMODITY_TYPE);    //设置商品种类（0201消费类）
        tPaymentRequest.dicOrder.put("BuyIP", "");                                     //IP
        tPaymentRequest.dicOrder.put("ExpiredDate", "");                               //设定订单保存时间
        //2、订单明细
        LinkedHashMap orderitem = new LinkedHashMap();
        orderitem.put("SubMerName", payOrder.getMchId());                              //设定二级商户名称
        orderitem.put("SubMerId", payOrder.getMchId());                                //设定二级商户代码
        orderitem.put("SubMerMCC", "0000");                                            //设定二级商户MCC码
        orderitem.put("SubMerchantRemarks", "商户");                                    //二级商户备注项
        orderitem.put("ProductID", payOrder.getPayOrderId());                          //商品代码，预留字段
        orderitem.put("ProductName", payOrder.getSubject());                           //商品名称
        orderitem.put("UnitPrice", AmountUtil.convertCent2Dollar(payOrder.getAmount()+""));//商品总价
        orderitem.put("Qty", "1");                                                     //商品数量
        orderitem.put("ProductRemarks", "");                                           //商品备注项
        orderitem.put("ProductType", "消费类");                                         //商品类型
        orderitem.put("ProductDiscount", "");                                          //商品折扣
        orderitem.put("ProductExpiredDate", "");                                       //商品有效期
        tPaymentRequest.orderitems.put(1, orderitem);
        //3、生成支付请求对象
        String paymentType = "A";
        tPaymentRequest.dicRequest.put("PaymentType", paymentType);                     //设定支付类型
        String paymentLinkType  = "1";
        tPaymentRequest.dicRequest.put("PaymentLinkType", paymentLinkType);             //设定支付接入方式

        if (paymentType.equals(Constants.PAY_TYPE_UCBP) && paymentLinkType.equals(Constants.PAY_LINK_TYPE_MOBILE))
        {
            tPaymentRequest.dicRequest.put("UnionPayLinkType","0");                     //当支付类型为6，支付接入方式为2的条件满足时，需要设置银联跨行移动支付接入方式
        }
        DBApplicationConfig dbConfig = getDBApplicationConfig();

        String notifyUrl = dbConfig.getConfig4PayNotifyUrl();
        tPaymentRequest.dicRequest.put("ReceiveAccount", "");                           //设定收款方账号
        tPaymentRequest.dicRequest.put("ReceiveAccName", "");                           //设定收款方户名
        tPaymentRequest.dicRequest.put("NotifyType", AbcpayConfig.NOTIFY_TYPE);         //设定通知方式
        tPaymentRequest.dicRequest.put("ResultNotifyURL", notifyUrl);                   //设定通知URL地址
        tPaymentRequest.dicRequest.put("MerchantRemarks", "");                          //设定附言
        tPaymentRequest.dicRequest.put("IsBreakAccount", AbcpayConfig.IS_BREAK_ACCOUNT);//设定交易是否分账
        tPaymentRequest.dicRequest.put("SplitAccTemplate", "");                         //分账模版编号

        _log.info("{}请求数据:{},{}", getChannelName(), tPaymentRequest.dicRequest, tPaymentRequest.dicOrder);
        //发送请求
        JSON json = tPaymentRequest.postRequest();
        String string = json.getIJsonString();
        _log.info("{}请求结果:{}", getChannelName(), string);
        //返回参数解析
        JSONObject jsonObject = JsonUtil.getJSONObjectFromJson(string);
        JSONObject msg = jsonObject.getJSONObject("MSG");
        JSONObject message = msg.getJSONObject("Message");

        //订单状态
        String code = message.getString("ReturnCode");
        String paymentURL = "";
        String payMethod = "";
        if("0000".equals(code)) {
            if (AbcpayConfig.PAY_TYPE_QR.equals(type)) {
                paymentURL = message.getString("PaymentURL");
                payMethod = PayConstant.PAY_METHOD_FORM_JUMP;
                StringBuffer payForm = new StringBuffer();
                payForm.append("<form style=\"display: none\" action=\""+paymentURL+"\" method=\"post\">");
                payForm.append("<input type=\"submit\" value=\"立即支付\" style=\"display:none\" >");
                payForm.append("</form>");
                payForm.append("<script>document.forms[0].submit();</script>");
                retObj.setPayUrl(payForm.toString());
            }else if (AbcpayConfig.PAY_TYPE_ALIPAY_WX.equals(type)) {
                paymentURL = message.getString("OneQRForAll");
                payMethod = PayConstant.PAY_METHOD_CODE_IMG;
                retObj.setCodeUrl(paymentURL); // 二维码支付链接
                retObj.setCodeImgUrl(dbConfig.getConfig4PayUrl() + "/qrcode_img_get?url=" + paymentURL + "&widht=200&height=200");
            }else if (AbcpayConfig.PAY_TYPE_ALIPAY_H5.equals(type) || AbcpayConfig.PAY_TYPE_WX_H5.equals(type)) {

                String toPayUrl = dbConfig.getConfig4PayUrl() + "/"+AbcpayConfig.CHANNEL_NAME+"/payment/pay_wap.html";
                // 获取农行聚合支付地址
                String payForAll = message.getString("OneQRForAll");
                // 生成二维码连接地址
                String codeImgUrl = dbConfig.getConfig4PayUrl() + "/qrcode_img_get?url=" + payForAll + "&widht=200&height=200";

                JSONObject paramObj = new JSONObject();
                paramObj.put("amount", AmountUtil.convertCent2Dollar(payOrder.getAmount()+""));
                paramObj.put("imgUrl", codeImgUrl);
                paramObj.put("payOrderId", payOrder.getPayOrderId());
                paramObj.put("payType", type);

                String param = MyBase64.encode(paramObj.toJSONString().getBytes());
                StringBuffer payForm = new StringBuffer();
                payForm.append("<form style=\"display: none\" action=\""+toPayUrl+"\" method=\"post\">");
                payForm.append("<input name=\"param\" value=\""+param+"\" >");
                payForm.append("<input type=\"submit\" value=\"立即支付\" style=\"display:none\" >");
                payForm.append("</form>");
                payForm.append("<script>document.forms[0].submit();</script>");
                retObj.setPayUrl(payForm.toString());
                // 生成 payJumpUrl
                paymentURL = toPayUrl + "?param=" + param;
                // 跳转方式
                payMethod = PayConstant.PAY_METHOD_FORM_JUMP;
            }
            retObj.setPayJumpUrl(paymentURL);
            retObj.setPayMethod(payMethod);

            commonService.payOrderService.updateStatus4Ing(payOrder.getPayOrderId(), null);
            return retObj;
        }else {
            return ApiBuilder.bizError("操作失败!");
        }
    }

    /**
     * 查询订单
     * @param payOrder
     * @return
     */
    @Override
    public QueryRetMsg query(PayOrder payOrder) {

        String logPrefix = "【农行支付订单查询】";
        String payOrderId = payOrder.getPayOrderId();

        _log.info("{}开始查询,payOrderId={}", logPrefix, payOrderId);
        String payTypeID = AbcpayConfig.PAY_TYPE_ID;
        String queryTpye = "false";

        try {
            QueryOrderRequest tQueryRequest = new QueryOrderRequest();
            tQueryRequest.queryRequest.put("PayTypeID", payTypeID);    //设定交易类型
            tQueryRequest.queryRequest.put("OrderNo", payOrder.getPayOrderId());    //设定订单编号 （必要信息）
            tQueryRequest.queryRequest.put("QueryDetail", queryTpye);//设定查询方式

            JSON json = tQueryRequest.postRequest();
            String code = json.GetKeyValue("ReturnCode");
            if ("0000".equals(code)) {
                //4、获取结果信息
                String orderInfo = json.GetKeyValue("Order");
                if (orderInfo.length() < 1) {
                    _log.info("查询结果为空orderInfo={}", orderInfo);
                    return QueryRetMsg.waiting();  //支付中
                }

                //1、还原经过base64编码的信息
                Base64 tBase64 = new Base64();
                String orderDetail = new String(tBase64.decode(orderInfo));
                json.setJsonString(orderDetail);

                String status = json.GetKeyValue("Status");
                if ("03".equals(status) || "04".equals(status)){
                    return QueryRetMsg.confirmSuccess(null);  // 成功
                }
            }
        } catch (Exception e) {
            _log.error(e, "");
        }
        return QueryRetMsg.waiting();  //支付中
    }

}
